package com.jlh.com.jlh;

import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ApidocAction extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        // TODO: insert action logic here

        // 获取数据上下文
        DataContext dataContext = e.getDataContext();

        // 获取到数据上下文后，通过CommonDataKeys对象可以获得该File的所有信息
        Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
        PsiFile psiFile = CommonDataKeys.PSI_FILE.getData(dataContext);

        PsiClass psiClass = getPsiClassFromContext(e,psiFile,editor);
        PsiMethod selectMethod = getSelectMethod(psiClass, editor);

        if (selectMethod == null){
            return;
        }
        PsiAnnotation[] annotations = selectMethod.getModifierList().getAnnotations();

        if (annotations == null || annotations.length == 0){
            return;
        }

        PsiAnnotation requestAnnotion = Stream.of(annotations).filter(m -> {
            for (MVCMethodEnums mvcMethodEnums : MVCMethodEnums.values()) {
                if (m.getQualifiedName().contains(mvcMethodEnums.getName())) {
                    return true;
                }
            }
            return false;
        }).findFirst().orElse(null);

        if (requestAnnotion == null){
            return;
        }

        MVCMethodEnums methodEnum = MVCMethodEnums.findByName(requestAnnotion.getQualifiedName());

        String httpType = methodEnum.httpType(requestAnnotion);
        String childPath = requestAnnotion.findDeclaredAttributeValue("value")
                .getText()
                .replaceAll("\"","");


        PsiAnnotation classRequestAnnotion = Stream.of(psiClass.getAnnotations())
                .filter(m->m.getQualifiedName().contains(MVCMethodEnums.RequestMapping.getName()))
                .findFirst()
                .orElse(null);

        String parentPath = classRequestAnnotion == null ? "" :
                classRequestAnnotion.findDeclaredAttributeValue("value").getText().replaceAll("\"","");

        String urlPath = (parentPath+"/"+childPath)
                .replaceAll("/\\*+","/")
                .replaceAll("//", "/");


        PsiElementFactory factory = JavaPsiFacade.getInstance(e.getProject()).getElementFactory();

        PsiDocComment docComment = selectMethod.getDocComment();


        StringBuilder docStr = new StringBuilder();
        docStr.append("/**\n");
        docStr.append("* ");
        docStr.append(DocumentUtils.getApiInfo(docComment,httpType,urlPath));
        docStr.append(DocumentUtils.getApiVersion(docComment));
        docStr.append(DocumentUtils.getApiName(selectMethod,psiClass));
        docStr.append(DocumentUtils.getApiGroup(docComment));
        String apiParamString = DocumentUtils.getApiParamString(selectMethod);
        if (StringUtils.isNotBlank(apiParamString)) {
            docStr.append(DocumentUtils.getApiParamString(selectMethod));
            docStr.append(DocumentUtils.getApiParamExmple(selectMethod));
        }
        docStr.append(DocumentUtils.getApiSuccessExample(docComment));
        docStr.append("\n*/");

        String doc = docStr.toString();

        PsiDocComment docCommentFromText = factory.createDocCommentFromText(doc);


        WriteCommandAction.runWriteCommandAction(e.getProject(),()->{
            if (docComment!=null) {
                docComment.delete();
            }
            psiClass.addBefore(docCommentFromText,selectMethod);
        });



    }




    private PsiMethod getSelectMethod(PsiClass psiClass,Editor editor){
        return Stream.of(psiClass.getMethods())
                .filter(s->{
                    String lineString=editor.getDocument().getText(TextRange.create(editor.getCaretModel().getVisualLineStart(),editor.getCaretModel().getVisualLineEnd()));
                    return s.getText().contains(lineString);
                }).findFirst().orElse(null);
    }

    private PsiClass getPsiClassFromContext(AnActionEvent e, PsiFile psiFile, Editor editor) {

        if (psiFile == null || editor == null) {
            return null;
        }
        //获取插入的model，并获取偏移量
        int offset = editor.getCaretModel().getOffset();
        //根据偏移量找到psi元素
        PsiElement element = psiFile.findElementAt(offset);
        //根据元素获取到当前的上下文的类
        return PsiTreeUtil.getParentOfType(element, PsiClass.class);
    }
}
